﻿Module main
    Public active As Boolean = True
    Public idInt As Integer = -1



    ''' <summary>
    ''' Main holder method, call this to start looping for user input
    ''' </summary>
    ''' <returns>bool, true app should end peacfully, false app encountered an error</returns>
    ''' <remarks>app should end right after this function returns a value</remarks>
    Public Function Main(ByRef _console As Console) As Boolean
        Dim strResponse As String
        PopulateCommands()


        Do While (active = True)
            Console.Write(vbNewLine & "Abzu: ")
            strResponse = Console.ReadLine
            readUI(strResponse)
        Loop
        Console.WriteLine("Bye...")
        Return True
        '        commandHandlers.help
    End Function
    ''' <summary>
    ''' Initialize basic commands
    ''' </summary>
    ''' <remarks></remarks>
    Sub PopulateCommands()
        'TODO: finish me
        command.registerCommand("help", String.Format("Provides help information for {0} registered commands", My.Application.Info.AssemblyName))
        command.cmdList("help").args.Add("[command]", "Optional, command to display help of, can specify more then 1")
        AddHandler command.cmdList("help").exec, AddressOf commandHandlers.help_EventHandler


        command.registerCommand("version1", String.Format("Displays version of {0} ", My.Application.Info.AssemblyName))
        AddHandler command.cmdList("version1").exec, AddressOf commandHandlers.version_EventHandler

        command.registerCommand("superlong", "This is a superlong description, to test the proper formating of the help menus, this is going to be very long")
        'AddHandler command.cmdList("").exec, AddressOf PopulateCommands

        'cmdSyntaxList.Add("addServer [instanceName] [game] [gameManager]")
        command.registerCommand("addServer", "register a new server instance with RSMA")
        command.cmdList("addServer").args.Add("instanceName", "Name of the Server instance to be added")
        command.cmdList("addServer").args.Add("game", "Game Type of the new Server Instance")
        command.cmdList("addServer").args.Add("gameManager", "gameManager of the new Server Instance")

        'cmdSyntaxList.Add("editServer [instanceName] [game] [gameManager]")
        command.registerCommand("editServer", "edit existing server instance")
        command.cmdList("editServer").args.Add("instanceName", " New Name of the Server instance")
        command.cmdList("editServer").args.Add("game", "New Game Type of the Server Instance")
        command.cmdList("editServer").args.Add("gameManager", "New gameManager of the Server Instance")



        'cmdSyntaxList.Add("generateFile [fileType] [serverInstance] [opt: targetLocation]")
        command.registerCommand("generateFile", "edit existing server instance")
        command.cmdList("generateFile").args.Add("fileType", " New Name of the Server instance")
        command.cmdList("generateFile").args.Add("serverInstance", "New Game Type of the Server Instance")
        command.cmdList("generateFile").args.Add("opt: targetLocation", "[optional] target location of the file to be generated")


        'cmdSyntaxList.Add("configure [module] [param]")
        command.registerCommand("configure", "manipulate module parameters")
        command.cmdList("configure").args.Add("module", "module name space to edit")
        command.cmdList("configure").args.Add("param", "param to modify")
        command.cmdList("configure").args.Add("opt: targetLocation", "[optional] target location of the file to be generated")
        'cmdSyntaxList.Add("configure vault [ipAddress] [url]")
        command.registerCommand("addGameManager", "register game manager")
        command.cmdList("addGameManager").args.Add("name", "name of the game manager")
        command.cmdList("addGameManager").args.Add("regex", "param to modify")

        command.registerCommand("addGame", "register game manager")
        command.cmdList("addGame").args.Add("name", "name of the game manager")
        command.cmdList("addGame").args.Add("gameManager", "game manager")

        command.registerCommand("loadComplex", "load complex file templates")
        'cmdSyntaxList.Add("configure FileMonitoring [mode]")
        'cmdSyntaxList.Add("status")
        'cmdSyntaxList.Add("addGame [game name] [game Manager]")
        'cmdSyntaxList.Add("registerFile [Server Instance] [file Type] [Location] [Watch mode]")
        'cmdSyntaxList.Add("addReservist([name])")
        'cmdSyntaxList.Add("removeReservist([name])")
        'cmdSyntaxList.Add("activateSlot [Reservist name] [guid] [Server Instance]")
        'cmdSyntaxList.Add("deactivateSlot [Reservist name] [guid] [Server Instance]")
        'cmdSyntaxList.Add("addAdmin [name] [guid] [rank] [server Instance]")
        'cmdSyntaxList.Add("removeAdmin [name] [guid] [rank] [server Instance]")
        'cmdSyntaxList.Add("List –d [what] [param1]")
        'cmdSyntaxList.Add("serverInstanceName [what: reservists, admins]")
    End Sub
    Sub readUI(ByVal ui As String)
        If (ui <> Nothing) Then
            Dim cmdParts() As Object = Nothing
            cmdParts = parse(ui, " ")
            If (cmdParts.Length > 1) Then
                If (cmdParts(2) IsNot Nothing Or cmdParts(2) IsNot Nothing) Then
                    analyzeUI(ui, cmdParts(0), cmdParts(1), cmdParts(2))
                Else
                    analyzeUI(ui, ui)
                End If
            Else
                'we call a sepereate function so we do not have to if the hell out of the analyzeUI sub thats made for commands with args and params to avoid null references.
                analyzeUI(cmdParts(0), cmdParts(0))
            End If
        End If
    End Sub
    ''' <summary>
    ''' For commands that require params and args
    ''' </summary>
    ''' <param name="ui">the entire user entry</param>
    ''' <param name="cmd">parsed command</param>
    ''' <param name="params">parsed params</param>
    ''' <param name="args">pased args</param>
    ''' <remarks></remarks>
    Sub analyzeUI(ByVal ui As String, Optional ByVal cmd As String = "", Optional ByVal params() As String = Nothing, Optional ByVal args() As String = Nothing)
        If (IsNumeric(InStr(ui, "/?")) And (InStr(ui, "/?")) <> 0) Then
            Console.WriteLine(InStr(ui, "/?"))
            Console.WriteLine("o noez")
        End If

        Try
            Select Case cmd
                Case Is = "quit", "exit"
                    active = False 'exit the loop
                Case Is = "clear"
                    Console.Clear()
                Case Nothing
                    Console.Write(_error.errorlist(0))
                Case Else
                    If (command.cmdList.ContainsKey(cmd)) Then
                        command.cmdList(cmd).main(params, args)
                    Else
                        Console.Write(_error.errorlist(1))
                    End If
            End Select
        Catch ex As Exception
            _error.printerror("Error: " & ex.Message, True, False)
        End Try
    End Sub

    Function getArgs(ByVal strVal() As String, ByVal strDelimiter As String)
        Dim ArgSeparators As String = " "
        Dim ParamSeperators As String = "/"
        Dim arrArgs() As String = strVal
        Dim i As Integer
        Dim j As Integer = 0
        Dim blDimensioned As Boolean = False

        For i = LBound(strVal) To UBound(strVal)
            If (strVal(i) <> Nothing) Then
                If (strVal(i) <> Nothing) Then
                    If blDimensioned = True Then
                        'Yes, so extend the array one element large than its current upper bound.
                        'Without the "Preserve" keyword below, the previous elements in our array would be erased with the resizing
                        ReDim Preserve arrArgs(0 To UBound(arrArgs) + 1)
                    Else
                        'No, so dimension it and flag it as dimensioned.
                        ReDim arrArgs(0 To 0)
                        blDimensioned = True
                    End If
                    arrArgs(j) = strVal(i).Trim("""")
                    j += 1
                End If
            End If
        Next
        If (arrArgs(0) <> Nothing) Then
            Return arrArgs
        End If
    End Function
    Function _seperateParse(ByVal parsed() As String, ByVal strParamDelimiter As String)
        Dim cmdParts(2) As Object
        Dim params(0), args(0) As String
        Dim bFirst As Boolean = True
        Dim bSecond As Boolean = True
        'first should be the command
        cmdParts(0) = parsed(0)
        Array.Clear(parsed, 0, 1)
        'check for parameters
        Try
            For i As Integer = 1 To parsed.Length - 1
                If (parsed(i).Chars(0) = strParamDelimiter And parsed(i).Length = 2) Then
                    If (bFirst) Then
                        params(0) = parsed(i)
                        Array.Clear(parsed, i, 1)
                        bFirst = False
                    Else
                        ReDim Preserve params(0 To UBound(params) + 1)
                        params(UBound(params)) = parsed(i)
                        Array.Clear(parsed, i, 1)
                    End If
                ElseIf (parsed(i) IsNot Nothing And parsed(i) <> Nothing And parsed(i) <> "" And parsed(i) <> " ") Then
                    If (bSecond) Then
                        args(0) = parsed(i)
                        Array.Clear(parsed, i, 1)
                        bSecond = False
                    Else
                        ReDim Preserve args(0 To UBound(args) + 1)
                        args(UBound(args)) = parsed(i)
                        Array.Clear(parsed, i, 1)
                    End If
                End If
            Next
        Catch ex As Exception
            Console.WriteLine("Exception occurred in SeperateParse: [" & ex.GetType().ToString() & "] " & ex.Message)
        End Try
        If (params.Length = 1 And params(0) = Nothing) Then
            params = Nothing
        End If
        If (args.Length = 1 And args(0) = Nothing) Then
            args = Nothing
        End If
        cmdParts(1) = params
        cmdParts(2) = args
        Return cmdParts
    End Function
    Function parse(ByVal strval As String, ByVal delimitor As Char, Optional ByVal ignoreQuotation As Boolean = False)
        Dim temp(0) As String
        Dim itemp As Integer = 0
        Dim iStart As Integer = 0
        Dim iEnd As Integer = 0
        Dim iholder As Integer = 0
        Dim iFirstQuote As Integer = strval.IndexOf("""", 1)
        Dim iFirstDelim As Integer = strval.IndexOf(delimitor, 1)
        Dim trimChars() As Char = {"""", delimitor}


        Dim sHolder As String = Nothing
        'find first occurance of the delimitor and start looking from there on, if there isnt one, then this is a stand alone command
        If (iFirstDelim = -1) Then
            ''this is a stand alone command or invalid
            temp(0) = strval
            Return temp
        Else
            If (iFirstDelim > iFirstQuote And iFirstQuote <> -1 And iFirstDelim <> -1) Then itemp = iFirstQuote Else itemp = iFirstDelim
            iEnd = strval.IndexOf(delimitor, itemp)
            temp(0) = strval.Substring(iStart, itemp - iStart)

            iholder = itemp
        End If

        Try
            For i As Integer = iholder To strval.Length - 1
                sHolder = strval.Chars(i)
                If (strval.Chars(i) = delimitor) Then
                    'everything before this gets added to temp()
                    'make sure the next char to the next delmin is not a quote
                    itemp = strval.IndexOf(delimitor, i + 1)
                    iFirstQuote = strval.IndexOf("""", i + 1)

                    If (itemp = -1) Then
                        itemp = strval.Length - 1
                        ReDim Preserve temp(0 To UBound(temp) + 1)
                        temp(UBound(temp)) = strval.Substring(i, itemp - i + 1).Trim(trimChars)
                    ElseIf (iFirstQuote < itemp And iFirstQuote <> -1) Then
                        itemp = strval.IndexOf("""", iFirstQuote + 1)
                        ReDim Preserve temp(0 To UBound(temp) + 1)
                        temp(UBound(temp)) = strval.Substring(i, itemp - i + 1).Trim(trimChars)
                        i = itemp
                    Else
                        ReDim Preserve temp(0 To UBound(temp) + 1)
                        temp(UBound(temp)) = strval.Substring(i, itemp - i + 1).Trim(trimChars)
                        i = itemp - 1
                    End If



                ElseIf (strval.Chars(i) = """") Then
                    'find the next quote
                    itemp = strval.IndexOf("""", i + 1)
                    ReDim Preserve temp(0 To UBound(temp) + 1)
                    temp(UBound(temp)) = strval.Substring(i, itemp - i + 1).Trim(trimChars)
                    i = itemp
                End If
            Next i
        Catch ex As Exception
            _error.printerror("Exception occurred in List: [" & ex.GetType().ToString() & "] " & ex.Message, True, False)
            _error.printerror(vbTab & "Parsed UI: " & """" & strval & """", True, False)
            _error.printerror(vbTab & ex.StackTrace, True, False)
        End Try
        Return _seperateParse(temp, "-")
    End Function
    Function inString(ByVal search As String, ByVal str As String) As Boolean
        If (IsNumeric(InStr(str, search))) Then 'And (InStr(str, search) <> 0)) Then
            Return True
        Else
            Return False
        End If
    End Function
    Sub printParse(ByVal ui As String, ByVal cmd As String, ByVal params() As String, ByVal args() As String)
        Console.WriteLine("User Entered: " & ui)
        Console.WriteLine("Command Parsed: " & cmd)
        Console.WriteLine("Params Parsed:")
        For Each param As String In params
            Console.WriteLine(vbTab & param)
        Next param
        Console.WriteLine("Args Parsed:")
        For Each arg As String In args
            Console.WriteLine(vbTab & "Args Parsed: " & arg)
        Next arg
    End Sub

    Sub exampleProgressMain()
        Dim i As Integer
        'Console.Title = "averagecoder.net"
        Console.WriteLine()
        'Console.Write("SIMPLEPROGRESSBAR DEMO" & vbNewLine)
        Console.Write("----------------------" & vbNewLine & vbNewLine)

        Console.Write("-> With total limit specified" & vbNewLine & vbNewLine)
        For i = 1 To 100000
            If (i / 100) > 0 Then
                RenderProgressBar(100000, i, 3, Console.CursorTop)
            End If
        Next

        Console.WriteLine()
        Console.WriteLine()

        Console.Write("-> Without the total limit" & vbNewLine & vbNewLine)
        For i = 1 To 100000
            If (i / 100) > 0 Then
                RenderProgressBar(0, i, 3, Console.CursorTop)
            End If
        Next

        Console.WriteLine()
        Console.WriteLine()

        Console.Write("   Press any key to exit :)" & vbNewLine & vbNewLine)
        Console.ReadLine()
    End Sub
    ''' <summary>
    ''' Renders a progress bar to the console
    ''' </summary>
    ''' <param name="intMaxValue">max number of steps</param>
    ''' <param name="intProgress">current step</param>
    ''' <param name="intLeftPos">spoace from the left</param>
    ''' <param name="intTopPos">space from the top</param>
    ''' <remarks></remarks>
    Sub RenderProgressBar(ByVal intMaxValue As Integer, ByVal intProgress As Integer, ByVal intLeftPos As Integer, ByVal intTopPos As Integer)
        'http://averagecoder.net/simple-progress-bar-function-for-your-vbnet-console-application.htm
        Dim strResult As String
        Dim intPercent As Integer

        If (intMaxValue > 0) Then
            intPercent = Math.Round((intProgress / intMaxValue) * 100, 0)
            If intPercent >= 10 Then
                strResult = "| " & intPercent & "% |" & StrDup(intPercent \ 10, "=") & StrDup(10 - (intPercent \ 10), " ") & "|"
            Else
                strResult = "| " & intPercent & "% |" & StrDup(10, " ") & "|"
            End If
        Else
            intPercent = intProgress
            strResult = "| " & FormatNumber(intPercent, 0) & " |"
        End If
        Console.CursorVisible = False
        Console.SetCursorPosition(intLeftPos, intTopPos)
        Console.Write(strResult)
        Console.CursorVisible = True
    End Sub
    ''' <summary>
    ''' Handles help command
    ''' </summary>
    ''' <param name="_cmd">optional, command to display help of</param>
    ''' <remarks></remarks>
    Sub help(Optional ByVal _cmd As String = Nothing)
        Dim i_desc As Integer = Console.BufferWidth - 21
        If (_cmd Is Nothing) Then 'if we have no command to display help of...
            'print all commands
            For Each cmd As KeyValuePair(Of String, command) In command.cmdList
                If (cmd.Value.description.Length > i_desc) Then 'need to split this into two lines with a trailing carrage return
                    'lets be efficent and just tack it to a var
                    Dim i_desc_lineSpan As Integer = ((cmd.Value.description.Length / i_desc) - 1)
                    Console.WriteLine("{0,-20}{1}", cmd.Key, cmd.Value.description.Substring(0, i_desc))
                    Dim i_pointer As Integer = i_desc

                    While i_pointer < cmd.Value.description.Length 'while our pointer is not beyond the length of the command description
                        Console.WriteLine("{0,-20}{1}", " ", cmd.Value.description.Substring(i_pointer, (cmd.Value.description.Length - i_pointer)))
                        i_pointer += i_desc
                    End While
                    Console.WriteLine()
                Else : Console.WriteLine("{0,-20}{1}", cmd.Key, cmd.Value.description)
                End If

            Next cmd
        Else
            'print help for that command

        End If
    End Sub
End Module
